<template>
  <vxe-pulldown ref="pullRef" placement="bottom-start" style="width: 100%;">
    <template #default>
      <ltext
        ref="jselectRef"
        :model-value="modelValue"
        :disabled="disabled"
        :clearable="clearable"
        :size="size"
        :style="{ width: width}"
        :placeholder="placeholder"
        @focus="focusEvent"
        @clear="clear"
        @input="changeInput"
      />
    </template>
    <template #dropdown>
      <div class="pull-wrapper" ref="wrapperRef">
        <template v-if="state.list.length > 0">
          <el-tree
            v-model="treeVal"
            node-key="id"
            :data="state.list"
            :props="defaultProps"
            @current-change="currentChange"
          />
        </template>
        <div style="text-align: center" v-else>
          <el-empty description="无记录" :image-size="30"></el-empty>
        </div>
      </div>
    </template>
  </vxe-pulldown>
</template>

<script>
import tool from '@/utils/tool'
export default {
  props: {
    width: { type: [String, Number], default: '' },
    modelValue: { type: [String, Number], default: '' },
    text: { type: [String, Number], default: '' },
    sql: { type: String, default: '' },
    size: { type: String, default: 'default' },
    valueKey: { type: String, default: 'id' },
    labelKey: { type: String, default: 'name' },
    height: { type: [String, Number], default: '' },
    disabled: { type: Boolean, default: false },
    clearable: { type: Boolean, default: true },
    list: { type: [String, Array], default: '' },
    readonly: { type: Boolean, default: false }, // 必填
    required: { type: Boolean, default: false }, // 必填
    border: { type: Boolean, default: true }, // 禁用
    className: { type: String, default: '' }, // 自定义样式
    placeholder: { type: String, default: '' }, // 自定义样式
    borderColor: { type: String, default: '' }, // 边框色
    bgColor: { type: String, default: '' }, // 背景色
    listWidth: { type: Number, default: 0 }, // 下拉框宽度
    cat: { type: String, default: '' }, // 取数据cat分类
    options: {
      type: Array,
      default: () => {
        return []
      }
    } // 如果传入值
  },
  data() {
    return {
      show: false,
      treeVal: null,
      state: {
        list: []
      },
      currentIndex: -1,
      defaultProps: {
        label(data) {
          return data.name
        }
      }
    }
  },
  emits: ['update:modelValue', 'update:id', 'Esc', 'enter', 'change'],
  methods: {
    currentChange(data) {
      this.setData(data)
    },
    focusEvent() {
      this.currentIndex = -1
      this.changeInput(this.modelValue ? this.modelValue : '')
    },
    isOpen() {
      return this.$refs.pullRef.isPanelVisible()
    },
    keydownEvent(e) {
      let key = e.key ? e.key : e.$event.key
      switch (key) {
        case 'Enter':
          {
            if (this.currentIndex > -1 && this.currentIndex < this.state.list.length) {
              this.setData(this.state.list[this.currentIndex])
            }
          }
          break
        case 'ArrowDown':
          {
            if (!e.ctrlKey) {
              if (!this.isOpen()) return
              if (this.currentIndex < this.state.list.length - 1) {
                this.currentIndex++
                this.scrollToOption(true, this.state.list[this.currentIndex])
              } else {
                let optWrapperElem = this.$refs.wrapperRef
                this.currentIndex = 0
                optWrapperElem.scrollTo(0, 0)
              }
            }
          }
          break
        case 'ArrowUp':
          {
            if (!e.ctrlKey) {
              if (!this.isOpen()) return
              if (this.currentIndex > 0 && this.currentIndex <= this.state.list.length - 1) {
                this.currentIndex--
              } else {
                this.currentIndex = this.state.list.length - 1
              }
              this.scrollToOption(false, this.state.list[this.currentIndex])
            }
          }
          break
        case 'Escape':
          {
            this.hidePanel()
            this.$emit('Esc')
          }
          break
      }
    },
    clear() {
      this.$emit('update:modelValue', '')
      this.$emit('update:id', null)
      this.$emit('change', null)
      this.currentIndex = -1
      this.hidePanel()
    },
    changeInput(val) {
      let value = val
      if (typeof val === 'object') {
        value = val.value
      }
      let searchTxt = value ? tool.xe.trim(value) : ''

      if (this.list.length > 0) {
        if (searchTxt) {
          this.state.list = this.list.filter((row) => {
            return row[this.labelKey].indexOf(searchTxt) !== -1
          })
        }
        this.openPanel()
      }
      if (this.sql) {
        let sql = this.sql
        if (searchTxt) sql += +` and ${this.labelKey} like '%${searchTxt}%' `
        tool.post('common/doSql', { sql: sql }).then((ret) => {
          this.state.list = tool.toArrayTree(ret.data)
          this.openPanel()
        })
      }
      if (this.cat) {
        this.state.list = []
        tool.post('common/dropdown', { cat: this.cat, keyWord: val }).then((ret) => {
          if (ret.stat) {
            this.state.list = ret.data
            this.openPanel()
          }
        })
      }
    },
    openPanel() {
      this.$refs.pullRef.showPanel()
    },
    hidePanel() {
      this.$refs.pullRef.hidePanel()
    },
    mouseDown(e, item) {
      e.preventDefault()
      this.setData(item)
      this.$emit('enter')
    },
    scrollToOption(isAlignBottom, item) {
      let optWrapperElem = this.$refs.wrapperRef
      let panelElem = this.$refs.wrapperRef
      let optElem = panelElem.querySelector('#id' + item.id)
      if (optWrapperElem && optElem) {
        let wrapperHeight = panelElem.offsetHeight
        let offsetPadding = 5
        if (isAlignBottom) {
          if (optElem.offsetTop + optElem.offsetHeight - panelElem.scrollTop > wrapperHeight) {
            optWrapperElem.scrollTo(0, optElem.offsetTop + optElem.offsetHeight - wrapperHeight)
          }
        } else {
          optWrapperElem.scrollTo(0, optElem.offsetTop - offsetPadding)
        }
      }
    },
    setData(item) {
      this.$emit('update:modelValue', item[this.labelKey])
      this.$emit('update:id', item[this.valueKey])
      this.$emit('change', { id: item[this.valueKey], name: item[this.labelKey] })
      this.hidePanel()
    },
    setList(list) {
      if (list) {
        if (typeof list === 'object') {
          this.state.list = list
        }
        if (typeof list === 'string') {
          this.state.list = JSON.parse(list)
        }
      }
    },
    down(e) {
      e.preventDefault()
    },
    addItemClick() {}
  }
}
</script>

<style lang="scss">
.list-item2 {
  height: 30px;
  line-height: 30px;
  padding-left: 5px;
  padding-right: 30px;
  white-space: nowrap;
  &.active {
    background-color: #dcdfe6;
  }
  &:hover {
    background-color: #dcdfe6;
    cursor: pointer;
  }
}
.el-input-group__append {
  padding: 0 2px !important;
}
.more {
  &:hover {
    cursor: pointer;
  }
}
.pull-wrapper {
  height: 200px;
  overflow: auto;
  //box-shadow: 0 2px 5px 0 #E5E5E5;
  box-shadow: 0 0 6px 2px rgba(0, 0, 0, 0.1);
  width: auto;
  .add-row {
    border-top: 1px solid #dcdfe6;
    height: 30px;
    padding-top: 5px;
    text-align: center;
    color: #8a8f97;
    background-color: var(--el-bg-color-page);
    &:hover {
      cursor: pointer;
      color: #1e9fff;
    }
  }
}
</style>